package model

import (
	"time"

	"bmember/pkg/util"
)

const (
	// ScheduleRechargeOrder 充值订单定时任务
	ScheduleRechargeOrder int8 = 1

	ScheduleWaiting = 1
	ScheduleDoing   = 2
	ScheduleSuccess = 3
	ScheduleFailed  = 4
)

// Schedules 定时任务
type Schedules struct {
	// 自增id
	Id int64 `json:"id" sql:"id"`
	// 任务类型
	SchType int8 `json:"eta_type" sql:"sch_type"`
	// 重试次数
	Retry int8 `json:"retry" sql:"retry"`
	// 状态：1~待执行，2~执行中, 3~执行成功 4~执行失败
	Status int8 `json:"status" sql:"status"`
	// 定时任务参数
	Param []byte `json:"param" sql:"param"`
	// 预期执行时间
	ExecuteTime time.Time `json:"execute_time" sql:"execute_time"`
	// 错误信息
	ErrMsg string `json:"err_msg" sql:"err_msg"`
	// 创建时间
	CreatedAt time.Time `json:"created_at" sql:"created_at"`
	// 更新时间
	UpdatedAt time.Time `json:"updated_at" sql:"updated_at"`
}

func NewSechdule(schType int8, param []byte, executeTime time.Time) *Schedules {
	now := util.GetNow()
	return &Schedules{
		SchType:     schType,
		Retry:       0,
		Status:      ScheduleWaiting,
		Param:       param,
		ExecuteTime: executeTime,
		CreatedAt:   now,
		UpdatedAt:   now,
	}
}

type OrderScheduleOp int8

const (
	// SchOpRecharge 订单支付状态查询
	SchOpRecharge OrderScheduleOp = 1
)

// OrderSchedule 订单定时任务
type OrderSchedule struct {
	// 订单号
	OrderId int64 `json:"order_id"`
	// 操作
	Op OrderScheduleOp `json:"op"`
}

// NewRechargeSchedule 新建订单定时任务
func NewRechargeSchedule(OrderId int64, op OrderScheduleOp) *Schedules {
	sch := &OrderSchedule{
		OrderId: OrderId,
		Op:      op,
	}
	b, _ := json.Marshal(sch)
	exTime := util.GetNow().Add(5 * time.Second)
	return NewSechdule(ScheduleRechargeOrder, b, exTime)
}

func (s *Schedules) setErrMsg(err error) {
	if err == nil {
		return
	}
	s.ErrMsg = err.Error()
	if len(s.ErrMsg) > 1024 {
		s.ErrMsg = s.ErrMsg[:1024]
	}
}

func (s *Schedules) AddRetry(err error) {
	s.Retry += 1
	s.SetExcuteTime()
	s.Status = ScheduleWaiting
	s.setErrMsg(err)
}

func (s *Schedules) SetExcuteTime() {
	now := util.GetNow()
	switch s.Retry {
	case 0:
		s.ExecuteTime = now.Add(1 * time.Second)
	case 1:
		s.ExecuteTime = now.Add(5 * time.Second)
	case 2:
		s.ExecuteTime = now.Add(15 * time.Second)
	case 3:
		s.ExecuteTime = now.Add(2 * time.Minute)
	case 5:
		s.ExecuteTime = now.Add(5 * time.Minute)
	default:
		s.ExecuteTime = now.Add(30 * time.Minute)
	}
	s.UpdatedAt = now
}

// Success 成功
func (s *Schedules) Success() {
	s.Status = ScheduleSuccess
	s.UpdatedAt = util.GetNow()
}

// Doing 执行中
func (s *Schedules) Doing() {
	s.Status = ScheduleDoing
	s.UpdatedAt = util.GetNow()
}

// Failed 失败
func (s *Schedules) Failed(err error) {
	s.Status = ScheduleFailed
	s.UpdatedAt = util.GetNow()
	s.setErrMsg(err)
}

// GetRechargeParam 获取订单定时任务参数
func (s *Schedules) GetRechargeParam() *OrderSchedule {
	if s.SchType != ScheduleRechargeOrder {
		return nil
	}
	if s.Param == nil {
		return nil
	}
	ret := &OrderSchedule{}
	_ = json.Unmarshal(s.Param, ret)
	return ret
}

// NeedMail 是否需要发送提醒邮件
func (s *Schedules) NeedMail() bool {
	if s.Retry > 5 && s.Status != ScheduleSuccess {
		return true
	}
	return false
}
